home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 16 / CU Amiga Magazine's Super CD-ROM 16 (1997-10-16)(EMAP Images)(GB)[!][issue 1997-11].iso / CUCD / Online / HBBS / Source / Node / Node_Serial.c < prev    next >
C/C++ Source or Header  |  1997-08-28  |  13KB  |  535 lines

  1. #include <string.h>
  2. #include <math.h>
  3. #include <stdio.h>
  4. #include <exec/types.h>
  5. #include <libraries/locale.h>
  6. #include <exec/memory.h>
  7. #include <dos/dosextens.h>
  8. #include <intuition/screens.h>
  9. #include <intuition/intuition.h>
  10. #include <intuition/gadgetclass.h>
  11. #include <libraries/gadtools.h>
  12. #include <diskfont/diskfont.h>
  13. #include <utility/utility.h>
  14. #include <graphics/gfxbase.h>
  15. #include <devices/console.h>
  16. #include <workbench/workbench.h>
  17. #include <graphics/scale.h>
  18. #include <clib/locale_protos.h>
  19. #include <clib/exec_protos.h>
  20. #include <clib/wb_protos.h>
  21. #include <clib/intuition_protos.h>
  22. #include <clib/gadtools_protos.h>
  23. #include <clib/graphics_protos.h>
  24. #include <clib/utility_protos.h>
  25. #include <clib/diskfont_protos.h>
  26.  
  27. #include <dos/dos.h>
  28. #include <dos/dostags.h>
  29. #include <stdlib.h>
  30. #include <stdio.h>
  31. #include <ctype.h>
  32. #include <time.h>
  33. #include <libraries/reqtools.h>
  34.  
  35. #include <clib/alib_protos.h>
  36. #include <clib/dos_protos.h>
  37. #include <clib/reqtools_protos.h>
  38.  
  39. #include "NodeGUI.h"
  40.  
  41. #include <devices/serial.h>
  42. #include <hardware/cia.h>
  43.  
  44. #include <clib/exec_protos.h>
  45. #include <clib/alib_protos.h>
  46.  
  47. #include "NodeGUI.h"
  48.  
  49. #define NOTMAIN
  50.  
  51. #define ClrSignal(s)  SetSignal(0,s)
  52.  
  53. #include <hbbs/types.h>
  54. #include <hbbs/defines.h>
  55. #include <hbbs/structures.h>
  56. #include <hbbs/strings.h>
  57. #include <hbbs/errors.h>
  58. #include <hbbs/shared_protos.h>
  59. #include <hbbs/Files.h>
  60.  
  61. #include "Node_Input_protos.h"
  62. //#include "Node_Console_protos.h"
  63.  
  64. #include <HBBS/Hbbscommon_protos.h>
  65. #ifdef __SASC
  66. #include <HBBS/hbbscommon_pragmas_sas.h>
  67. #else
  68. #include <HBBS/hbbscommon_pragmas_stc.h>
  69. #endif
  70.  
  71. #include <HBBS/Hbbsnode_protos.h>
  72. #ifdef __SASC
  73. #include <HBBS/Hbbsnode_pragmas_sas.h>
  74. #else
  75. #include <HBBS/Hbbsnode_pragmas_stc.h>
  76. #endif
  77.  
  78. extern struct NodeData *N_ND;
  79. extern struct BBSGlobalData *BBSGlobal;
  80. extern struct Library *HBBSCommonBase;
  81. extern struct Library *HBBSNodeBase;
  82.  
  83. char errstr[2048]; // big enough ?
  84.  
  85. char LastChar=0;
  86.  
  87. void SerReset( void )
  88. {
  89.   // this routine reads in all waiting data from the serial port and then dumps it!
  90.   UBYTE *mem;
  91.   ULONG bytes;
  92.  
  93.   if (bytes=SerQueryData())
  94.   {
  95.     if (mem=AllocVec(bytes,MEMF_PUBLIC))
  96.     {
  97.       WaitSerReadBlock(mem,bytes); // *C* ooh naughty.. should really have somekind of wait() here..
  98.  
  99. //      if (N_ND->ConOK)
  100. //      {
  101. //        ConWriteStr("Serial Port had this data in it's buffer:\r\n");
  102. //        ConWriteData(mem,bytes);
  103. //        ConWriteStr("End Dump\r\n");
  104. //      }
  105.       FreeVec(mem);
  106.     }
  107.   }
  108. }
  109.  
  110. void CleanupSerial( void )
  111. {
  112.   if (!N_ND->NodeDevice.SysopNode)
  113.   {
  114.     if (N_ND->SerBuffer)
  115.     {
  116.       if (N_ND->SerPort)
  117.       {
  118.         if (N_ND->SerWrite)
  119.         {
  120.           if (N_ND->SerOPEN)
  121.           {
  122.             if (N_ND->SerRead)
  123.             {
  124.               SerReset();
  125.               AbortSerRead(); // will only abort id request submitted..
  126.               FreeVec(N_ND->SerRead);
  127.             }
  128.             CloseDevice((struct IORequest*)N_ND->SerWrite);
  129.             N_ND->SerOPEN=FALSE;
  130.           }
  131.           DeleteExtIO((struct IORequest*)N_ND->SerWrite);
  132.         }
  133.         DeletePort(N_ND->SerPort);
  134.       }
  135.       FreeVec(N_ND->SerBuffer);
  136.     }
  137.   }
  138.   N_ND->SerOK=FALSE;
  139. }
  140.  
  141. V_BOOL OpenSerial( void )
  142. {
  143.   N_ND->SerWaiting=FALSE;
  144.   N_ND->SerOK=FALSE;
  145.   N_ND->SerOPEN=FALSE;
  146.   if (!N_ND->NodeDevice.SysopNode)
  147.   {
  148.     if (N_ND->SerBuffer=AllocVec(DEF_SERBUFLEN,MEMF_PUBLIC))
  149.     {
  150.       N_ND->SerBufferLen=DEF_SERBUFLEN;
  151.       if (N_ND->SerPort=CreatePort(0,0))
  152.       {
  153.         if (N_ND->SerWrite = (struct IOExtSer *) CreateExtIO(N_ND->SerPort,(ULONG)sizeof(struct IOExtSer)))
  154.         {
  155.  
  156.           N_ND->SerWrite->io_SerFlags       = SERF_7WIRE;
  157.  
  158.           if (!(OpenDevice((STRPTR)N_ND->NodeDevice.SerialDevice,(ULONG)N_ND->NodeDevice.SerialUnit,(struct IORequest *)N_ND->SerWrite,0L) ))
  159.           {
  160. //            N_ND->SerWrite->io_SerFlags       &= ~SERF_XDISABLED; // ENABLE XON/XOFF
  161.  
  162. //            N_ND->SerWrite->io_RBufLen=8192;
  163.  
  164. // note: hydracom wasworking with rbuf left at defualt with 8n1.device on a1200 with serial port in 7wire & shared mode
  165.  
  166.             N_ND->SerWrite->io_Baud           = N_ND->NodeDevice.SerialBaud;
  167.             N_ND->SerWrite->IOSer.io_Command  = SDCMD_SETPARAMS;
  168.             DoIO((struct IORequest *)N_ND->SerWrite);
  169.  
  170.             N_ND->SerOPEN=TRUE;
  171.  
  172.             if (N_ND->SerRead = (struct IOExtSer*)AllocVec(sizeof(struct IOExtSer),MEMF_PUBLIC) )
  173.             {
  174.               // duplicate data...
  175.               memcpy(N_ND->SerRead,N_ND->SerWrite,sizeof(struct IOExtSer));
  176.               SerReset();
  177.               N_ND->SerOK=TRUE;
  178.               return(TRUE);
  179.             }
  180.           }
  181.           else HBBS_DoErrorMessage(EMSG_NODEVICE,N_ND->NodeNum,NULL);
  182.         }
  183.       }
  184.     }
  185.     CleanupSerial();
  186.   }
  187.   return(FALSE);
  188. }
  189.  
  190.  
  191.  
  192. ULONG ModemGetLine( void )
  193. {
  194.   ULONG ReturnedSigs;
  195.   UBYTE CurrentChar[2]={0,0}; // 2 chars, use ¤tchar for null terminated string type..
  196.   ULONG retval=IN_NOTHING; // this must NOT be returned to the caller!!!!!
  197.   struct TimerData *TD;
  198.  
  199.   N_ND->CurrentLine[0]=0; // null terminate the string..
  200.  
  201.   if (TD=SubmitTimer(N_ND->NodeTimer,N_ND->NodeDevice.MaxCommandWait,0))
  202.   {
  203.     do
  204.     {
  205.       if (!N_ND->SerWaiting)
  206.       {
  207.         SendSerReadData();
  208.       }
  209.  
  210.       N_ND->SerSig=DEF_SERSIG;
  211.       N_ND->TimerSig=DEF_TIMERSIG;
  212.  
  213.       // we cant use SetupSigs() and WaitAllSigs() because if we are resetting
  214.       // the modem after a LOGIN_LOCAL sersigs is set to 0... :-)
  215.  
  216.  
  217.       ReturnedSigs=Wait(N_ND->SerSig | N_ND->TimerSig);
  218.  
  219.       while (HandleSerSigs(ReturnedSigs) && retval==IN_NOTHING)
  220.       {
  221.  
  222.         // if DumpModem is enabled then write out every single char that we get when talking to
  223.         // the modem.
  224.  
  225.         if (N_ND->NodeDevice.DumpModem)
  226.         {
  227.           printf("%d \"",N_ND->IBuffer[0]);
  228.  
  229.           if (N_ND->IBuffer[0]>=0x20 && N_ND->IBuffer[0]!=127) printf("%c",N_ND->IBuffer[0]);
  230.  
  231.           printf("\" ");
  232.         }
  233.         // ok, we got some data from somehwere...
  234.  
  235.         CurrentChar[0]=N_ND->IBuffer[0];
  236.  
  237.         if (CurrentChar[0]>=0x20 && CurrentChar[0]!=127) // i.e. not unprintable or a control char..
  238.         {
  239.           strcat(N_ND->CurrentLine,CurrentChar);
  240.         }
  241.         else
  242.         {
  243.           if (CurrentChar[0]=='\r' && LastChar!='\n' && LastChar !='\r')
  244.           {
  245.             if (strlen(N_ND->CurrentLine)>0) retval=IN_GOTLINE;
  246.           }
  247.  
  248.           if (CurrentChar[0]=='\n'  && LastChar!='\n' && LastChar !='\r')
  249.           {
  250.             if (strlen(N_ND->CurrentLine)>0) retval=IN_GOTLINE;
  251.           }
  252.         }
  253.  
  254.         LastChar=N_ND->IBuffer[0];
  255.       }
  256.  
  257.       if ((retval==IN_NOTHING) && (CheckTimer(N_ND->NodeTimer,TD)))
  258.       {
  259.         TD=NULL;
  260.         retval=IN_TIMEOUT;
  261.       }
  262.     }
  263.     while (retval==IN_NOTHING);
  264.     if (TD) AbortTimer(N_ND->NodeTimer,TD);
  265.  
  266.     if (N_ND->NodeDevice.ModemDebug && N_ND->ConOK)
  267.     {
  268.       ConWriteStr(N_ND->CurrentLine);
  269.       ConWriteStr(str_CRLF);
  270.     }
  271.     if (N_ND->SerWaiting) AbortSerRead();
  272.   }
  273.  
  274.   if (N_ND->NodeDevice.DumpModem)
  275.   {
  276.     printf("'%s' \n",N_ND->CurrentLine);
  277.   }
  278.  
  279.   return(retval);
  280. }
  281.  
  282. void ModemError(char *command, char *result)
  283. {
  284.   if (N_ND->NodeDevice.ModemLog)
  285.   {
  286.     sprintf(errstr,"When Sending the command \"%s\" the modem returned \"%s\"",command,result);
  287.  
  288.     HBBS_LogError(N_ND->NodeSettings.ModemLogFile,ERR_GENERAL,errstr,TYPE_WARNING);
  289.   }
  290.  
  291.   HBBS_LogError(N_ND->NodeSettings.NodeLogFile,ERR_GENERAL,"Modem Error!",TYPE_WARNING);
  292. }
  293.  
  294. void TurnEchoOn( void )
  295. {
  296.   struct Node *node;
  297.   short retriesleft;
  298.   BOOL Done;
  299.   ULONG result;
  300.  
  301.  
  302.   PutText("\033[37;0m\n");
  303.   for (node=N_ND->NodeDevice.TurnOnEcho->lh_Head;node->ln_Succ;node=node->ln_Succ)
  304.   {
  305.     if (node->ln_Name)
  306.     {
  307.       Done=FALSE;
  308.       retriesleft=N_ND->NodeDevice.EchoRetries;
  309.       do
  310.       {
  311.         if (retriesleft!=N_ND->NodeDevice.EchoRetries)
  312.         {
  313.           ConWriteStr("Retrying Modem...\n\r");
  314.         }
  315.  
  316.         retriesleft--;
  317.         Delay(N_ND->NodeDevice.TurnOnEchoDelay);
  318.         SerReset();
  319.         SerWriteStr(node->ln_Name);
  320.         SerWriteStr("\r");
  321.         if (N_ND->NodeDevice.UseCRLF)
  322.         {
  323.           SerWriteStr("\n");
  324.         }
  325.         if (result=ModemGetLine()==IN_GOTLINE)
  326.         {
  327.           // ok, got some input..
  328.  
  329.           if (stricmp(node->ln_Name,N_ND->CurrentLine)==0)
  330.           {  // echo is already on, so discard this line and read another line..
  331.             result=ModemGetLine();
  332.           }
  333.           if (result==IN_GOTLINE)
  334.           {
  335.             if (stricmp("OK",N_ND->CurrentLine)==0) Done=TRUE;
  336.           }
  337.         }
  338.       } while (!Done && retriesleft>0);
  339.     }
  340.   }
  341.   SerReset();
  342. }
  343.  
  344. V_BOOL SendModemString(char *str)
  345. {
  346.   ULONG err=1;
  347.   ULONG loop,loop2;
  348.   BOOL linemismatch;
  349.  
  350.   char *cvtstr;
  351.  
  352.   if (cvtstr=DupStr(str))
  353.   {
  354.  
  355.     // remove the '~'s fromt the string so that we can compare the returned string from the modem
  356.     // (the modem won't return the '~'s because it'll never get them!
  357.  
  358.     loop=0,loop2=0;
  359.     while (str[loop])
  360.     {
  361.       if (str[loop]!='~')
  362.       {
  363.         cvtstr[loop2]=str[loop];
  364.       }
  365.       loop2++;
  366.       loop++;
  367.     }
  368.     cvtstr[loop2]=0;
  369.  
  370.     loop2=N_ND->NodeDevice.CommandRetries;
  371.  
  372.     do
  373.     {
  374.  
  375.       // this loop sends the command to the modem and wait for the characters to
  376.       // be echoed back.  if we don't get back what we send we try it again!
  377.  
  378.       loop=N_ND->NodeDevice.CommandRetries;
  379.       do
  380.       {
  381.         Delay(N_ND->NodeDevice.DelayBetweenCmds);
  382.         SerReset(); //clear all crap before we send our new string..
  383.         SerDelayWriteStr(str); // send the command to the modem
  384.         SerWriteStr("\r");
  385.         if (N_ND->NodeDevice.UseCRLF)
  386.         {
  387.           SerWriteStr("\n");
  388.         }
  389.         ModemGetLine(); // then check the modem echo'd the chars we sent it.
  390.         if (linemismatch=(stricmp(cvtstr,N_ND->CurrentLine)!=0 ? TRUE : FALSE)) // compare with cvtstr and not str..
  391.         {
  392.           // modem did not retunr the same string we sent it, the modem's local echo must be off so turn it on
  393.           TurnEchoOn();
  394.         }
  395.       } while (loop-- && linemismatch); // if we had a line mismatch then retry sending the command now that echo is on.
  396.  
  397.       // now wait the modem's responce from the command we sent it.
  398.  
  399.       // right if we are here then we know we're gonna get a blank line and a timeout
  400.       // or OK OR ERROR..  if we don't get OK then we retry the command...
  401.       ModemGetLine();
  402.  
  403.     } while (loop2-- && stricmp(N_ND->CurrentLine,"OK")!=0 && (err=stricmp(N_ND->CurrentLine,"ERROR"))==0);
  404.     if (!err) ModemError(str,N_ND->CurrentLine);
  405.  
  406.     FreeStr(cvtstr);
  407.   }
  408.   return(err);
  409. }
  410.  
  411. void OffHook( void )
  412. {
  413.   if (N_ND->NodeSettings.UseDevice)
  414.   {
  415.     SendModemString(N_ND->NodeDevice.OffHookString);
  416.   }
  417. }
  418.  
  419. void ReOpenSerial( void )
  420. {
  421.  
  422.   // closing and opening the serial port has the effect of dropping dtr,
  423.   // forcing a hangup of the modem.
  424.  
  425.   V_SMALLNUM loop=N_ND->NodeDevice.ReOpenRetries;
  426.   if (!N_ND->NodeDevice.SysopNode)
  427.   {
  428.     CleanupSerial();
  429.  
  430.     while (loop-- && N_ND->SerOK==FALSE)
  431.     {
  432.       Delay(N_ND->NodeDevice.ReOpenDelay);
  433.       OpenSerial();
  434.     }
  435.  
  436.     if (!N_ND->SerOK)
  437.     {
  438.       HBBS_LogError(BBSGlobal->ErrorLogFile,ERR_GENERAL,ESTR_NOSERIAL,TYPE_CRITICAL);
  439.     }
  440.   }
  441. }
  442.  
  443. void SendHangupCommands( void )
  444. {
  445.   struct Node *node;
  446.  
  447.   for (node=N_ND->NodeDevice.CommandModeString->lh_Head;node->ln_Succ;node=node->ln_Succ)
  448.   {
  449.     if (node->ln_Name) SerDelayWriteStr(node->ln_Name);
  450.   }
  451.   SendModemString(N_ND->NodeDevice.HangUpString);
  452. }
  453.  
  454. void HangUp( void )
  455. {
  456.  
  457.   if (N_ND->NodeSettings.UseDevice)
  458.   {
  459.     if (!N_ND->NodeDevice.NullModemCable)
  460.     {
  461.       if (N_ND->NodeDevice.DropDTRHangup)
  462.       {
  463.         ReOpenSerial();
  464.       }
  465.       else
  466.       {
  467.         SendHangupCommands();
  468.       }
  469.       if (CarrierLost())
  470.       {
  471.         if (N_ND->ConOK) ConWriteStr("Hungup OK.\r\n");
  472.       }
  473.       else
  474.       {
  475.         if (N_ND->NodeDevice.DropDTRHangup)
  476.         {
  477.           sprintf(errstr,"Could not hangup using DTR.");
  478.           HBBS_LogError(N_ND->NodeSettings.NodeLogFile,ERR_GENERAL,errstr,TYPE_WARNING);
  479.           SendHangupCommands();
  480.         }
  481.         else
  482.         {
  483.           sprintf(errstr,"Could not hangup using commands, trying DTR.");
  484.           HBBS_LogError(N_ND->NodeSettings.NodeLogFile,ERR_GENERAL,errstr,TYPE_WARNING);
  485.           ReOpenSerial();
  486.         }
  487.  
  488.         if (!CarrierLost())
  489.         {
  490.           sprintf(errstr,"Could not hangup using hangup commands either.");
  491.           HBBS_LogError(N_ND->NodeSettings.NodeLogFile,ERR_GENERAL,errstr,TYPE_WARNING);
  492.         }
  493.  
  494.       }
  495.       OffHook();
  496.     }
  497.     else
  498.     {
  499.       ReOpenSerial();
  500.     }
  501.   }
  502. }
  503.  
  504. V_BOOL InitModem( void )
  505. {
  506.   struct Node *node;
  507.  
  508.   if (N_ND->NodeSettings.UseDevice)
  509.   {
  510.     if (N_ND->NodeDevice.ModemDebug && N_ND->ConOK)
  511.     {
  512.       ConWriteStr("Initialising Modem...\n\r");
  513.     }
  514.  
  515.     TurnEchoOn();
  516.     Delay(N_ND->NodeDevice.DelayBetweenCmds);
  517.     for (node=N_ND->NodeDevice.ModemInit->lh_Head;node->ln_Succ;node=node->ln_Succ)
  518.     {
  519.       if (node->ln_Name) SendModemString(node->ln_Name);
  520.     }
  521.     // wait a bit nd dump any data.
  522.     Delay(N_ND->NodeDevice.DelayBetweenCmds);
  523.     SerReset();
  524.  
  525.     if (!N_ND->NodeSettings.Iconified)
  526.     {
  527.       // set gadget on noe gui window so that it says "ONHOOK"
  528.       GT_SetGadgetAttrs(NodeWndGadgets[NodeWnd_OffHook],NodeWnd,NULL,GTCY_Active,0,TAG_DONE);
  529.     }
  530.  
  531.   }
  532.   return(TRUE);
  533. }
  534.  
  535.